<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>AOP Style Interception</title>

    <style type="text/css">
        <!--
        .style1 {
            font-family: "Courier New", Courier, monospace
        }

        -->
    </style>
</head>
<body>
<p>PicoContainer has a rudimentary Aspect Orientated Programing (AOP) capability with its 'Interception' behavior. With
    respect to the methods of a component, both
    before and after invocation, control can be handed to an interceptor. You can intercept a method call:</p>
<ul>
    <li> before it is invoked (and optionally veto its invocation, with an alternate return value).</li>
    <li> after it is invoked (and optionally override the return value).</li>
</ul>
<p>There are some limitations:</p>
<ul>
    <li>it will only work for interface/impl separated components</li>
    <li>it needs a class that implements the interface in question
        <ul>
            <li>all of the methods need null implementations, even if not intended to be intercepted</li>
        </ul>
    </li>
    <li>will (likely) break if there's deep recursion into Intercepted instances</li>
    <li>you can't intercept an implementation's static methods</li>
    <li>it is not possible to modify a method's arguments</li>
    <li>the constructor's invocation for the component is not interceptable</li>
    <li>the component's fields are not interceptable</li>
    <li>only one component invoking the methods on another component will be intercepted.
        <ul>
            <li>components and related classes calling their own methods will not be intercepted</li>
        </ul>
    </li>
</ul>
<div class="source">
      <pre>public static class BiteReporter implements Apple {
    private Intercepted.Controller controller;

    public BiteReporter(Intercepted.Controller controller) {
        this.controller = controller;

    } 
    public boolean takeBite(int grams) {
        System.out.println(&quot;Bite of &quot; + grams + &quot; grams of apple '&quot; + controller.getInstance().getName() + &quot;'&quot;);
        return false; // ignored, but necessary.
    }
}
...
pico = new DefaultPicoContainer(new Intercepting());
pico.addComponent(Apple.class, BraeburnApple.class);
Intercepted intercepted = pico.getComponentAdapter(Apple.class).findAdapterOfType(Intercepted.class);
intercepted.addPreInvocation(Apple.class, new BiteReporter(intercepted.getController()));
// see also Intercpeted.addPostInvocation(...) method.
Apple a1 = pico.getComponent(Apple.class);
a1.takeBite(100); 
// prints Bite of 100 grams of apple 'Braeburn' 
// ... irrespective of what else Braeburn.takeBite(int) does.
  </pre>
</div>
<div class="source">
    <pre>pico = new DefaultPicoContainer();
pico.as(INTERCEPT).addComponent(Apple.class, BraeburnApple.class);
// etc</pre>
</div>
<div class="source">
    <pre>pico = new PicoBuilder.withInterception().build();
pico.addComponent(Apple.class, BraeburnApple.class);
// etc</pre>
</div>
<div class="source">
    <pre>pico = new PicoBuilder.withBehaviors(interception()).build();
pico.addComponent(Apple.class, BraeburnApple.class);
// etc</pre>
</div>
<p><b>Fine grained participation in interception</b><br/>Assuming you're passing in the Interceptor to the classes
    you're using for interception of a component, you can
    participate in the fate of the method call. For a 'pre' invocation, you can veto the calling of the 'real'
    method. </p>

<div class="source">
    <pre>    public boolean takeBite(int grams) {
        if (grams &gt; 50) {
             controller.veto();

        }
        return false; // will be passed back to the caller.
    }
</pre>
</div>
<p>For a 'post' invocation, you can override the return value of the 'real' method. </p>

<div class="source">
    <pre>    public boolean takeBite(int grams) {        

        if (grams &gt; 50) {
             controller.override();
             (Apple) realApple = (Apple) controller.getInstance();
             realApple.takeBite(-1 * grams); // undo !
        }
        return false; // will be passed back to the caller.
    }
</pre>
</div>
<p>Also for a 'post' invocation, you can access the return value of the 'real' method. </p>

<div class="source">
    <pre>    public boolean takeBite(int grams) {        

        boolean rv = (boolean) controller.getOriginalRetVal();
        if (rv == false) {
             // do something !
        }
        return true; // ignored as no 'override'
    }
</pre>
</div>
</body>


</html>
